/**
 * Copyright (c) 2018-2022, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contains: string ops by arch
 *
 * Change Logs:
 * Date           Author            Notes
 * 2022-07-30     GuEe-GUI          Init
 */

#include <base/string.h>

char *NX_StrCopy(const char *dest, const char *src)
{
    int d0, d1, d2;

    __asm__ volatile (
        "1: lodsb\n\t"
        "   stosb\n\t"
        "   testb   %%al, %%al\n\t"
        "   jne     1b"
        : "=&S" (d0), "=&D" (d1), "=&a" (d2)
        : "0" (src), "1" (dest)
        : "memory");

    return (char *)dest;
}

NX_Size NX_StrCopyN(char *dest, const char *src, NX_Size len)
{
    int d0, d1, d2, d3;

    __asm__ volatile (
        "1: decl    %2\n\t"
        "   js      2f\n\t"
        "   lodsb\n\t"
        "   stosb\n\t"
        "   testb   %%al, %%al\n\t"
        "   jne     1b\n\t"
        "   rep ;   stosb\n"
        "2:"
        : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
        : "0" (src), "1" (dest), "2" (len)
        : "memory");

    return NX_StrLen(src);
}

int NX_StrCmp(const char *a, const char *b)
{
    int d0, d1;
    int res;

    __asm__ volatile (
        "1: lodsb\n\t"
        "   scasb\n\t"
        "   jne     2f\n\t"
        "   testb   %%al, %%al\n\t"
        "   jne     1b\n\t"
        "   xorl    %%eax, %%eax\n\t"
        "   jmp     3f\n"
        "2: sbbl    %%eax, %%eax\n\t"
        "   orb     $1, %%al\n"
        "3:"
        : "=a" (res), "=&S" (d0), "=&D" (d1)
        : "1" (a), "2" (b)
        : "memory");

    return res;
}

int NX_StrCmpN(const char * s1, const char * s2, NX_Size n)
{
    int res;
    int d0, d1, d2;

    __asm__ volatile (
        "1: decl    %3\n\t"
        "   js      2f\n\t"
        "   lodsb\n\t"
        "   scasb\n\t"
        "   jne     3f\n\t"
        "   testb   %%al, %%al\n\t"
        "   jne     1b\n"
        "2: xorl    %%eax, %%eax\n\t"
        "   jmp     4f\n"
        "3: sbbl    %%eax, %%eax\n\t"
        "   orb     $1, %%al\n"
        "4:"
        : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
        : "1" (s1), "2" (s2), "3" (n)
        : "memory");

    return res;
}

int NX_StrLen(const char *str)
{
    int d0;
    NX_Size res;

    __asm__ volatile (
        "   repne\n\t"
        "   scasb"
        : "=c" (res), "=&D" (d0)
        : "1" (str), "a" (0), "0" (0xffffffffu)
        : "memory");

    return (~res - 1);
}

char *NX_StrChr(const char *s, int c)
{
    int d0;
    char *res;

    __asm__ volatile (
        "   movb    %%al, %%ah\n"
        "1: lodsb\n\t"
        "   cmpb    %%ah, %%al\n\t"
        "   je      2f\n\t"
        "   testb   %%al, %%al\n\t"
        "   jne     1b\n\t"
        "   movl    $1, %1\n"
        "2: movl    %1, %0\n\t"
        "   decl    %0"
        : "=a" (res), "=&S" (d0)
        : "1" (s), "0" (c)
        : "memory");

    return res;
}

char *NX_StrCat(char *strDest , const char *strSrc)
{
    int d0, d1, d2, d3;

    __asm__ volatile (
        "   repne\n\t"
        "   scasb\n\t"
        "   decl    %1\n"
        "1: lodsb\n\t"
        "   stosb\n\t"
        "   testb   %%al, %%al\n\t"
        "   jne     1b"
        : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
        : "0" (strSrc), "1" (strDest), "2" (0), "3" (0xffffffffu)
        : "memory");

    return strDest;
}
